package com.iot08.api.utils.wxpay;

import com.alibaba.fastjson.JSONObject;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.*;


import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

/**
 * 提供Map<String,Object>转XML，XML转Map<String,Object>
 */


public class NewXMLUtil {


        /**
         *
         * 通过Map创建XML,Map可以多层转换
         *
         * @param params
         * @return	String-->XML
         */
        public static String createXmlByMap(String parentName,JSONObject params,boolean isCDATA){
            Document doc = DocumentHelper.createDocument();
            doc.addElement(parentName);
            String xml = iteratorXml(doc.getRootElement(),parentName,params,isCDATA);
            return formatXML(xml);
        }

        /**
         *
         * 通过Map创建XML,Map可以多层转换
         * 可以自定义parent节点
         *
         * @param params
         * @return	String-->XML
         */
        public static String createXmlByMap(String parentName,JSONObject params){
            Document doc = DocumentHelper.createDocument();
            doc.addElement(parentName);
            String xml = iteratorXml(doc.getRootElement(),parentName,params,false);
            return formatXML(xml);
        }

        /**
         *
         * 通过Map创建XML,Map可以多层转
         * 固定节点parent为Document
         *
         * @param params
         * @return	String-->XML
         */
        public static String createXmlByMap(JSONObject params){
            String parentName = "Request";
            Document doc = DocumentHelper.createDocument();
            doc.addElement(parentName);
            String xml = iteratorXml(doc.getRootElement(),parentName,params,false);
            return formatXML(xml);
        }

        /**
         *
         * MapToXml循环遍历创建xml节点
         * 此方法在value中加入CDATA标识符
         *
         * @param element 根节点
         * @param parentName 子节点名字
         * @param params map数据
         * @return String-->Xml
         */

        @SuppressWarnings("unchecked")
        public static String iteratorXml(Element element,String parentName,JSONObject params,boolean isCDATA) {
            Element e = element.addElement(parentName);
            Set<String> set = params.keySet();
            for (Iterator<String> it = set.iterator(); it.hasNext();) {
                String key = (String) it.next();
                if(params.get(key) instanceof Map) {
                    iteratorXml(e,key,(JSONObject)params.get(key),isCDATA);
                }else {
                    String value = params.get(key)==null?"":params.get(key).toString();
                    if(!isCDATA) {
                        e.addElement(key).addText(value);
                    }else {
                        e.addElement(key).addCDATA(value);
                    }
                }
            }
            return e.asXML();
        }

        /**
         * 格式化xml,显示为容易看的XML格式
         *
         * @param inputXML
         * @return
         */
        public static String formatXML(String inputXML){
            String requestXML = null;
            XMLWriter writer = null;
            Document document = null;
            try {
                SAXReader reader = new SAXReader();
                document = reader.read(new StringReader(inputXML));
                if (document != null) {
                    StringWriter stringWriter = new StringWriter();
                    OutputFormat format = new OutputFormat("	", true);//格式化，每一级前的空格
                    format.setNewLineAfterDeclaration(false);	//xml声明与内容是否添加空行
                    format.setSuppressDeclaration(false);		//是否设置xml声明头部
                    format.setNewlines(true);		//设置分行
                    writer = new XMLWriter(stringWriter, format);
                    writer.write(document);
                    writer.flush();
                    requestXML = stringWriter.getBuffer().toString();
                }
                return requestXML;
            } catch (Exception e1) {
                e1.printStackTrace();
                return null;
            }finally {
                if (writer != null) {
                    try {
                        writer.close();
                    } catch (IOException e) {

                    }
                }
            }
        }


        /**
         *
         * 通过XML转换为Map<String,Object>
         *
         * @param xml 为String类型的Xml
         * @return 第一个为Root节点，Root节点之后为Root的元素，如果为多层，可以通过key获取下一层Map
         */
        public static JSONObject createMapByXml(String xml) {
            Document doc = null;
            try {
                doc = DocumentHelper.parseText(xml);
            } catch (DocumentException e) {
                e.printStackTrace();
            }
            JSONObject map = new JSONObject();
            if (doc == null)
                return map;
            Element rootElement = doc.getRootElement();
            elementTomap(rootElement,map);
            return map;
        }

        /***
         *
         * XmlToMap核心方法，里面有递归调用
         *
         * @param outele
         * @param outmap
         */
        @SuppressWarnings("unchecked")
        public static JSONObject elementTomap (Element outele,JSONObject outmap) {
            List<Element> list = outele.elements();
            int size = list.size();
            if(size == 0){
                outmap.put(outele.getName(), outele.getTextTrim());
            }else{
                JSONObject innermap = new JSONObject();
                for(Element ele1 : list){
                    String eleName = ele1.getName();
                    Object obj =  innermap.get(eleName);
                    if(obj == null){
                        elementTomap(ele1,innermap);
                    }else{
                        if(obj instanceof java.util.Map){
                            List<Map<String, Object>> list1 = new ArrayList<Map<String, Object>>();
                            list1.add((Map<String, Object>) innermap.remove(eleName));
                            elementTomap(ele1,innermap);
                            list1.add((Map<String, Object>) innermap.remove(eleName));
                            innermap.put(eleName, list1);
                        }else{
                            elementTomap(ele1,innermap);
                            ((List<Map<String, Object>>)obj).add(innermap);
                        }
                    }
                }
                outmap.put(outele.getName(), innermap);
            }
            return outmap;
        }

        /**
         * Map or JSON 转换成Xml
         *
         * fastJSON实现了Map<String,Object> 所以此处直接传json 也可以的
         */
        public static String mapToXML(Map map, StringBuffer sb) {
            Set set = map.keySet();
            for (Iterator it = set.iterator(); it.hasNext(); ) {
                String key = (String) it.next();
                Object value = map.get(key);
                if (null == value)
                    value = "";
                if (value.getClass().getName().equals("java.util.ArrayList")) {
                    LinkedList list = (LinkedList) map.get(key);
                    sb.append("<" + key + ">");
                    for (int i = 0; i < list.size(); i++) {
                        HashMap hm = (HashMap) list.get(i);
                        mapToXML(hm, sb);
                    }
                    sb.append("</" + key + ">");

                } else {
                    if (value instanceof HashMap) {
                        sb.append("<" + key + ">");
                        mapToXML((HashMap) value, sb);
                        sb.append("</" + key + ">");
                    } else {
                        sb.append("<" + key + ">" + value + "</" + key + ">");
                    }
                }
            }

            return sb.toString();
        }

        public static void main(String[] args) {
            String result = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                    "<result  resultCode=\"0\">\n" +
                    "    <getDiskResult>\n" +
                    "        <parentCatalogID>0Q11diXl808e00019700101000000071</parentCatalogID>\n" +
                    "        <nodeCount>1</nodeCount>\n" +
                    "        <catalogList  length=\"1\">\n" +
                    "            <catalogInfo>\n" +
                    "                <catalogName>生词本</catalogName>\n" +
                    "                <catalogID>0Q11diXl808e03120231201151215bt2</catalogID>\n" +
                    "                <catalogType>0</catalogType>\n" +
                    "                <isShared>false</isShared>\n" +
                    "                <createTime>20231201151215</createTime>\n" +
                    "                <updateTime>20231201151948</updateTime>\n" +
                    "                <catalogLevel>4</catalogLevel>\n" +
                    "                <shareDoneeCount>0</shareDoneeCount>\n" +
                    "                <ETagOprType>1</ETagOprType>\n" +
                    "                <openType>0</openType>\n" +
                    "                <dirEtag>4194304</dirEtag>\n" +
                    "                <tombstoned>0</tombstoned>\n" +
                    "                <moved>0</moved>\n" +
                    "                <parentCatalogId>0Q11diXl808e03120231129161650n16</parentCatalogId>\n" +
                    "                <isFixedDir>0</isFixedDir>\n" +
                    "                <path>00019700101000000001/0Q11diXl808e00019700101000000071/0Q11diXl808e03120231129161650n16/0Q11diXl808e03120231201151215bt2</path>\n" +
                    "                <owner>13418100840</owner>\n" +
                    "                <modifier>13418100840</modifier>\n" +
                    "                <shareType>0</shareType>\n" +
                    "                <isIngested>1</isIngested>\n" +
                    "                <extProp3>\n" +
                    "                    <![CDATA[{\"creator\":\"13418100840\"}]]>\n" +
                    "                </extProp3>\n" +
                    "            </catalogInfo>\n" +
                    "        </catalogList>\n" +
                    "        <isCompleted>0</isCompleted>\n" +
                    "    </getDiskResult>\n" +
                    "</result>";

            result = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><result resultCode=\"0\"><getDiskResult><parentCatalogID>0Q11diXl808e00019700101000000071</parentCatalogID><nodeCount>1</nodeCount><contentList length=\"1\"><contentInfo><contentID>0Q11diXl808e06920231202110809dbk</contentID><contentName>newWordsNotebook.json</contentName><contentSuffix>json</contentSuffix><contentSize>162</contentSize><contentDesc></contentDesc><isShared>false</isShared><contentType>0</contentType><contentOrigin>2</contentOrigin><updateTime>20231202110809</updateTime><commentCount>0</commentCount><thumbnailURL></thumbnailURL><bigthumbnailURL></bigthumbnailURL><midthumbnailURL></midthumbnailURL><presentURL>http://download.mcloud.139.com:80/storageWeb/servlet/GetFileByURLServlet?root=/mnt/wfs146&amp;fileid=KMd5f09ded9df592b93c2175429be260eb.json&amp;ct=0&amp;type=2&amp;code=E6591D7113C25EE9AA75BFD36502C7965C655B25C50DFFA1FB0E0067CC5C159D&amp;exp=329&amp;account=MFExMWRpWGw4MDhl&amp;p=0&amp;ui=0Q11diXl808e&amp;ci=0Q11diXl808e06920231202110809dbk&amp;userSiteId=usersite-s&amp;cn=newWordsNotebook&amp;oprChannel=10230036&amp;dom=D962</presentURL><presentLURL></presentLURL><presentHURL></presentHURL><shareDoneeCount>0</shareDoneeCount><safestate>0</safestate><transferstate>0</transferstate><isFocusContent>0</isFocusContent><uploadTime>20231202110809</uploadTime><ETagOprType>1</ETagOprType><openType>0</openType><auditResult>0</auditResult><parentCatalogId>0Q11diXl808e03120231129161650n16</parentCatalogId><channel>10214200</channel><digest>CE94BA3A3487C0A3C15B5045D31BA9A8</digest><geoLocFlag>0</geoLocFlag><version></version><fileEtag>1842185668306242577</fileEtag><encryptFlag>0</encryptFlag><fileVersion>1842185668285308898</fileVersion><tombstoned>0</tombstoned><proxyID></proxyID><moved>0</moved><owner>13418100840</owner><modifier>13418100840</modifier><shareType>0</shareType><exif><createTime>19700101000000</createTime></exif><isIngested>1</isIngested><extInfo size=\"1\"><item><key>uploader</key><value>13418100840</value></item></extInfo><extProp3></extProp3></contentInfo></contentList><isCompleted>0</isCompleted></getDiskResult></result>";
            JSONObject resOB = NewXMLUtil.createMapByXml(result);

            JSONObject getDiskResult = resOB.getJSONObject("getDiskResult");
            //    JSONObject contentList = getDiskResult.getJSONObject("contentList");
            //    Object contentInfo = contentList.get("contentInfo");
            //    if (contentInfo instanceof Map){
            //        System.out.println("是对象");
            //    }else if (contentInfo instanceof ArrayList){
            //        System.out.println("是数组");
            //    }
            System.out.println(resOB.toJSONString());


            result = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                    "        <result  resultCode=\"0\">\n" +
                    "            <String>http://download.mcloud.139.com:80/storageWeb/servlet/downloadServlet?code=S00wUTExZGlYbDgwOGU4MzIxN3UybEdlUElI&amp;un=D0FA91881019A1D1BAF33E50CA8DF2E4A8EE71AE62420D6CE25A9B723D81980E&amp;dom=D962&amp;rate=0&amp;txType=0</String>\n" +
                    "        </result>";
            resOB = NewXMLUtil.createMapByXml(result);

            System.out.println(resOB.toJSONString());


            result = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                    "        <result  resultCode=\"0\">\n" +
                    "            <uploadResult>\n" +
                    "                <uploadTaskID>KB0Q11diXl808e22417u2lHCkNn</uploadTaskID>\n" +
                    "                <redirectionUrl>http://upload.mcloud.139.com:80/storageWeb/servlet/uploadFileServlet?uploadCode=S0IwUTExZGlYbDgwOGUyMjQxN3UybEhDa05u&amp;txType=0&amp;oprChannel=10230036&amp;dom=D961&amp;rate=0</redirectionUrl>\n" +
                    "                <newContentIDList  length=\"1\">\n" +
                    "                    <newContent>\n" +
                    "                        <contentID>0Q11diXl808e06920231202144445jvv</contentID>\n" +
                    "                        <contentName>outLineVoice.amr</contentName>\n" +
                    "                        <isNeedUpload>1</isNeedUpload>\n" +
                    "                        <fileEtag>1842240175971113056</fileEtag>\n" +
                    "                        <overridenFlag>0</overridenFlag>\n" +
                    "                        <fileVersion>1842240175971113057</fileVersion>\n" +
                    "                    </newContent>\n" +
                    "                </newContentIDList>\n" +
                    "            </uploadResult>\n" +
                    "        </result>";
            resOB = NewXMLUtil.createMapByXml(result);

            System.out.println(resOB.toJSONString());

            result = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                    "<result  resultCode=\"200000501\" desc=\"[501225|F9E37BA46CA04EF3B03917FCA5381B8F]Failed to invoke the service.0[NDA(100590)][Flag:F9E37BA46CA04EF3B03917FCA5381B8F]\">\n" +
                    "</result>";
            resOB = NewXMLUtil.createMapByXml(result);

            System.out.println(resOB.toJSONString());


            String xmlByMap = NewXMLUtil.createXmlByMap(JSONObject.parseObject("{\"getDisk\":{\"catalogID\":\"0Q11diXl808e03120231129161650n16\"}}"));
            System.out.println("xmlByMap:" + xmlByMap);
        }
}

